package com.bungarus.busi;

import com.bungarus.Access;
import com.bungarus.codec.protobuf.MessageProtobuf;
import com.bungarus.model.*;
import com.bungarus.processor.AccessNormalProcessor;
import com.bungarus.processor.AccessStatusProcessor;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import org.apache.log4j.Logger;

import java.net.InetSocketAddress;

/**
 * Handle the messages sent by busi server
 * Created by tang on 2018/11/19.
 */
@ChannelHandler.Sharable
public class ServerMediaHandler extends ChannelInboundHandlerAdapter {
    Logger logger = Logger.getLogger(ServerMediaHandler.class);
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        InetSocketAddress localAddress = (InetSocketAddress)ctx.channel().localAddress();
        if(msg instanceof MessageProtobuf.Message){
            MessageProtobuf.Message message = (MessageProtobuf.Message)msg;
            if(MessageType.HEARTBEAT_PING == message.getHeader().getType()){
                //send back pong
                ctx.writeAndFlush(MessageBuilder.buildHeartbeatPongMessage(message.getHeader().getId(), message.getHeader().getId2()));
            }
            else if(MessageType.ACK == message.getHeader().getType()) {
                DischargeQueue queue = Discharger.getQueueInstance();
                queue.removeFromQueue(Long.valueOf(message.getHeader().getId()));
            }
            else if(Access.PORT_7800 == localAddress.getPort()){
                logger.info("++++++++++ Message received : \n" + message.toString());
                //get IM message from busi layer, so deliver the message to the client
                SessionContainer sessionContainer = Access.getSessionContainer();
                String sessionId = message.getHeader().getSessionId();
                Session session = sessionContainer.findSession(sessionId);
                logger.debug("Session found in access: " + session);

                //make the end user's token same as which been saved in session
                MessageProtobuf.Message msgToEndUser;
                if(null != session && MessageType.OFFLINE != message.getHeader().getType()) {
                    msgToEndUser = MessageBuilder.buildMessage2EndUserWithToken(message, session.getToken());
                }
                else {
                    msgToEndUser = message;
                }

                MessageProcessor processor;
                if(MessageType.STATUS == msgToEndUser.getHeader().getType()) { //status sync message
                    processor = AccessStatusProcessor.getInstance();
                }
                else { // IM or IM_GROUP message
                    processor = AccessNormalProcessor.getInstance();
                }
                Channel channel = null;
                if(null != session) {
                    channel = sessionContainer.find(session); // find the receipt channel
                    if(null == channel){
                        logger.warn("Channel is not found for session id -> " + sessionId);
                    }
                }
                processor.process(msgToEndUser, ctx.channel(), channel);
            }
        }
        else {
            super.channelRead(ctx, msg);
        }
    }
}
